package org.balthie.demo.jdk.util.concurrent.locks.reenterrwlock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

//https://blog.csdn.net/qq_42651904/article/details/115026768
//https://www.bilibili.com/read/cv13299398
public class ReentrantReadWriteLockDemo {
	private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

	static volatile int readcount = 0;

	private double x;
	private double y;
	
//	AbstractQueuedSynchronizer.javaprivate volatile int state
//	state 64个bit， 前32位表示写锁（独占）， 后32位表示读锁（共享）
	public void move(double deltaX, double deltaY) {

		WriteLock writeLock = lock.writeLock(); // 获取写锁
		System.out.println(String.format("[%s] writeLock ", Thread.currentThread()));
		long duration = (long) (Math.random() * 100);
		long begin = System.currentTimeMillis();
		try {
			writeLock.lock();
			x += deltaX;
			y += deltaY;
//			模拟写入耗时
			TimeUnit.MILLISECONDS.sleep(duration);
		} catch (InterruptedException e) {
		} finally {
			writeLock.unlock(); // 释放写锁
			System.out.println(String.format("[%s] unlock  task duration[%s] writeLock [%s] mills",
					Thread.currentThread(), duration, System.currentTimeMillis() - begin));
		}
	}

	public double distanceFromOrigin() {
		// 注意下面两行代码不是原子操作
		// 假设x,y = (100,200)
		double currentX = x;
		// 此处已读取到x=100，但x,y可能被写线程修改为(300,400)
		double currentY = y;
		ReadLock readLock = lock.readLock(); // 获得一个读锁
		try {
			readLock.lock();
			System.out.println(String.format("[%s] readLock lock ", Thread.currentThread()));
			++readcount;
		} finally {
			if (readLock != null) {
				readLock.unlock(); // 释放写锁
				System.out.println(String.format("[%s] readLock unlock ReadHoldCount [%s] ReadLockCount[%s]", Thread.currentThread(), lock.getReadHoldCount(), lock.getReadLockCount()));
			}
		}
		return Math.sqrt(currentX * currentX + currentY * currentY);
	}
}
// 读写共享 sharedCount ，读操作会堵塞写
//Exception in thread "Thread-0" java.lang.Error: Maximum lock count exceeded
//at java.util.concurrent.locks.ReentrantReadWriteLock$Sync.fullTryAcquireShared(ReentrantReadWriteLock.java:528)
//at java.util.concurrent.locks.ReentrantReadWriteLock$Sync.tryAcquireShared(ReentrantReadWriteLock.java:488)
//at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared(AbstractQueuedSynchronizer.java:1282)
